// import View from "@/components/view";
// import Link from "@/components/link";

export let _Vue;

export function install(Vue) {
  //不会重复安装
  if (install.instaslled && _Vue === Vue) return;
  install.instaslled = true;

  _Vue = Vue;

  const isDef = (v) => v !== undefined;

  //为router-view组件关联路组件
  const registerInstance = (vm, callVal) => {
    let i = vm.$options._parentVnode;
    //调用vm.$options._parentVnode.data.registerRouteInstance方法
    //而这个方法只在router-view组件中存在，router-view组件定义在(../components/view.js,@71行)
    //所以，如果vm的父节点为router-view，则为router-view关联当前vm，即将当前vm做为router-view的路由组件
    if (
      isDef(i) &&
      isDef((i = i.data)) &&
      isDef((i = i.registerRouteInstance))
    ) {
      i(vm, callVal);
    }
  };
  Vue.mixin({
    beforeCreate() {
      // 这里只会进来一次，因为只有Vue根实例才会有router属性。
      if (isDef(this.$options.router)) {
        // 所以这里的this就是Vue根实例
        this._routerRoot = this;
        this._router = this.$options.router;
        this._router.init(this);
        // 将 _route 变成响应式
        Vue.util.defineReactive(this, "_route", this._router.history.current);
      } else {
        // 子组件会进入这里，这里也是把Vue根实例保存带_routerRoot属性上
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
      }
      //为router-view组件关联路由组件
      registerInstance(this, this);
    },
    destroyed() {
      //destroyed,hook触发时，取消router-view和路由组件的关联
      registerInstance(this);
    },
  });
  //在原型上注入$router、$route属性，方便快捷访问
  Object.defineProperty(Vue.prototype, "$router", {
    // 上面说到每个组件的_routerRoot都是Vue根实例，所以都能访问_router
    get() {
      return this._routerRoot._router;
    },
  });

  //每个组件访问到的$route，其实最后访问的都是Vue根实例的_route
  Object.defineProperty(Vue.prototype, "$route", {
    get() {
      return this._routerRoot._route;
    },
  });

  //注册router-view、router-link两个全局组件
  //   Vue.component("RouterView", View);
  //   Vue.component("RouterLink", Link);

  const strats = Vue.config.optionMergeStrategies;
  // use the same hook merging strategy for route hooks
  strats.beforeRouteEnter =
    strats.beforeRouteLeave =
    strats.beforeRouteUpdate =
      strats.created;
}
